import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { DesignerEnvType, DesignViewModelService, FormBasicService, FormBindingType, UniformEditorDataUtil } from '@farris/designer-services';
import { CollectionProp } from '../../common/property/collection-property-config';
import { DgControl } from '../../../../utils/dg-control';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { BindingEditorComponent, BindingEditorConverter } from '@farris/designer-devkit';
import { BuilderOptions, IDesignerHost } from '@farris/designer-element';
import { NoCodeCollectionProp } from '../../common/property/nocode-collection-property-config';

export class TableTdProp extends CollectionProp {
    envType: DesignerEnvType;
    propertyConfig: ElementPropertyConfig[];

    private controlCreatorSerivice: any;
    private schemaDOMMapping: any;
    private serviceHosts: any;
    constructor(serviceHosts: IDesignerHost, viewModelId: string, componentId: string) {
        super(serviceHosts, viewModelId, componentId);
        this.serviceHosts = serviceHosts;
        this.dgVMService = serviceHosts.getService('DesignViewModelService');
        this.schemaDOMMapping = serviceHosts.getService('SchemaDOMMapping');
        this.controlCreatorSerivice = serviceHosts.getService('ControlCreatorService');

        const formBasicService = serviceHosts.getService('FormBasicService') as FormBasicService;
        if (formBasicService) {
            this.envType = formBasicService.envType;
        }
    }

    getPropConfig(propertyData: any, isSimpleTable = false): ElementPropertyConfig[] {
        this.propertyConfig = [];

        if (!isSimpleTable) {
            // 基本信息属性
            const basicPropConfig = this.getBasicPropConfig();
            this.propertyConfig.push(basicPropConfig);

            // 外观属性
            const appearancePropConfig = this.getAppearancePropConfig();
            this.propertyConfig.push(appearancePropConfig);

            // 单元格属性
            const tdTypePropConfig = this.getTdTypePropConfig(propertyData, this.viewModelId);
            this.propertyConfig.push(tdTypePropConfig);
        }


        // 编辑器绑定、类型
        const editorPropConfigs = this.getEditorProperties(propertyData, this.viewModelId, isSimpleTable);
        this.propertyConfig = this.propertyConfig.concat(editorPropConfigs);

        return this.propertyConfig;

    }

    private getBasicPropConfig(): ElementPropertyConfig {
        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: [
                {
                    propertyID: 'id',
                    propertyName: '标识',
                    propertyType: 'string',
                    description: '组件的id',
                    readonly: true
                }
            ]
        };
    }

    private getAppearancePropConfig() {
        const props = this.getCommonAppearanceProperties();
        // props.push(
        //     {
        //         propertyID: 'colspan',
        //         propertyName: '占用列数',
        //         propertyType: 'string', // 数字控件变更检测可能有问题，先改成string
        //         description: '单元格占用的列个数',
        //         // min: 0,
        //         // max: 100,
        //         // decimals: 0,
        //         readonly: true
        //     },
        //     {
        //         propertyID: 'rowspan',
        //         propertyName: '占用行数',
        //         propertyType: 'string',
        //         description: '单元格占用的行个数',
        //         // min: 0,
        //         // max: 100,
        //         // decimals: 0,
        //         readonly: true
        //     }
        // );
        return {
            categoryId: 'appearance',
            categoryName: '外观',
            properties: props
        };
    }

    private getTdTypePropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        return {
            categoryId: 'tdType',
            categoryName: '单元格类型',
            tabId: 'tableTdEditor',
            tabName: '编辑器',
            properties: [
                {
                    propertyID: 'tdType',
                    propertyName: '单元格类型',
                    propertyType: 'select',
                    description: '单元格类型选择',
                    iterator: [{ key: 'staticText', value: '静态文本' }, { key: 'editor', value: '编辑框' }],
                }
            ],
            setPropertyRelates(changeObject: FormPropertyChangeObject, propData, parameters) {

                propertyData.staticText = {
                    text: '',
                    require: false
                };
                if (propertyData.editor && propertyData.editor.binding) {
                    // 清除字段绑定
                    const dgViewModel = self.dgVMService.getDgViewModel(viewModelId);
                    dgViewModel.removeField([propertyData.editor.binding.field]);
                }
                propertyData.editor = {
                    type: null,
                    binding: null
                };
                if (!propertyData.appearance) {
                    propertyData.appearance = { class: '' };
                }
                propertyData.appearance.class = propertyData.appearance.class.replace('farris-group-wrap--label', '').replace('farris-group-wrap--input', '');
                propertyData.appearance.class += changeObject.propertyValue === 'staticText' ?
                    ' farris-group-wrap--label' : ' farris-group-wrap--input';
            }
        };
    }

    private getEditorProperties(propertyData: any, viewModelId: string, isSimpleTable: boolean): ElementPropertyConfig[] {
        if (propertyData.tdType === 'staticText') {
            return this.getStaticTextPropConfig(propertyData, viewModelId);

        }

        if (propertyData.tdType === 'editor') {
            let configs = [];
            const editorTypes = this.getEditorPropConfig(propertyData, viewModelId);
            configs = configs.concat(editorTypes);

            if (propertyData.editor && propertyData.editor.type) {
                let editorProp;
                if (this.envType === DesignerEnvType.noCode) {
                    const noCodeColectionPro = new NoCodeCollectionProp(this.serviceHosts, this.viewModelId, this.componentId)
                    editorProp = noCodeColectionPro.getNoCodeFieldEditorProp(propertyData, 'tableTdEditor', isSimpleTable);
                } else {
                    editorProp = this.getFieldEditorProp(propertyData, 'tableTdEditor', isSimpleTable);

                }
                if (editorProp && editorProp.length > 0) {
                    configs = configs.concat(editorProp);
                }
            }
            return configs;
        }
    }
    /**
     * 静态文本属性
     * @param propertyData 属性值
     * @param viewModelId Viewmodel id
     * @returns ElementPropertyConfig[]
     */
    private getStaticTextPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig[] {
        return [{
            categoryId: 'text',
            categoryName: '文本',
            tabId: 'tableTdEditor',
            tabName: '编辑器',
            hide: propertyData.tdType !== 'staticText',
            enableCascade: true,
            parentPropertyID: 'staticText',
            propertyData: propertyData.staticText,
            properties: [
                {
                    propertyID: 'text',
                    propertyName: '单元格文本',
                    propertyType: 'string',
                    description: '单元格文本'
                },
                {
                    propertyID: 'require',
                    propertyName: '是否显示必填图标',
                    propertyType: 'unity',
                    description: '单元格是否显示必填图标',
                    editorParams: {
                        controlName: UniformEditorDataUtil.getControlName(propertyData),
                        constType: 'enum',
                        editorOptions: {
                            types: ['const', 'variable'],
                            enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
                            variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                            getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                            newVariableType: 'Boolean',
                            newVariablePrefix: 'is'
                        }
                    }
                }
            ]
        }];
    }

    /**
     * 编辑器单元格绑定属性
     * @param propertyData 属性值
     * @param viewModelId Viewmodel id
     */
    private getEditorPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig[] {
        const self = this;

        const { dgVMField, controlTypeList } = this.getControlTypeEnumData(propertyData, viewModelId);

        return [{
            categoryId: 'tableTdEditor_editorBinding',
            categoryName: '绑定',
            tabId: 'tableTdEditor',
            tabName: '编辑器',
            hide: propertyData.tdType !== 'editor',
            enableCascade: true,
            parentPropertyID: 'editor',
            propertyData: propertyData.editor,
            properties: [
                {
                    propertyID: 'binding',
                    propertyName: '绑定',
                    propertyType: 'modal',
                    description: '绑定的表单字段',
                    editor: BindingEditorComponent,
                    editorParams: {
                        viewModelId,
                        componentId: this.componentId,
                        controlType: propertyData.editor.type,
                        canChangeFieldType: true,
                        unusedOnly: true
                    },
                    converter: new BindingEditorConverter(),
                    showClearButton: true,
                    afterClickClearButton(oldValue: string) {
                        self.clearControlAfterBindingCleared(oldValue, viewModelId, propertyData);
                    }
                },
                {
                    propertyID: 'type',
                    propertyName: '控件类型',
                    propertyType: 'select',
                    description: '组件的类型',
                    iterator: controlTypeList,
                    visible: controlTypeList && controlTypeList.length > 0
                }
            ],
            setPropertyRelates(changeObject: FormPropertyChangeObject, propData, parameters) {
                switch (changeObject.propertyID) {
                    case 'binding': {
                        // 变更字段类型：修改原控件DOM结构
                        self.changeControlAfterBindingChanged(changeObject, propertyData, parameters, viewModelId);

                        const typeProp = this.properties.find(prop => prop.propertyID === 'type');
                        if (typeProp) {
                            typeProp.iterator = self.getControlTypeEnumData(propertyData, viewModelId);
                            typeProp.visible = typeProp.iterator.length > 0;
                        }
                        // 刷新实体树
                        self.refreshFormService.refreshSchamaTree.next();
                        break;
                    }
                    case 'type': {
                        if (propertyData.editor && propertyData.editor.binding) {
                            const bindingType = propertyData.editor.binding.type;
                            propertyData.editor = self.createControl(bindingType, dgVMField, changeObject.propertyValue, propertyData.editor);

                            changeObject['controlEditorChanged'] = true;
                        }

                    }
                }

            }
        }];
    }

    /**
     * 根据选择的绑定字段获取可选的控件类型
     * @param propertyData td属性值
     * @param viewModelId 所属视图模型id
     */
    private getControlTypeEnumData(propertyData: any, viewModelId: string) {
        if (!propertyData.editor || !propertyData.editor.binding) {
            return { dgVMField: null, controlTypeList: [] };
        }

        const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
        let controlTypeList = [];
        let dgVMField;
        if (propertyData.editor.binding.type === FormBindingType.Form) {
            dgVMField = dgViewModel.fields.find(f => f.id === propertyData.editor.binding.field);
            if (dgVMField) {
                controlTypeList = this.schemaDOMMapping.getEditorTypesByMDataType(dgVMField.type.name, dgVMField.multiLanguage, 'form', this.formBasicService.envType);
            }
        } else {
            dgVMField = this.domService.getVariableById(propertyData.editor.binding.field);
            if (dgVMField) {
                controlTypeList = this.schemaDOMMapping.getEditorTypesByMDataType(dgVMField.type, false, 'form', this.formBasicService.envType);
            }
        }

        return { dgVMField, controlTypeList };
    }

    private changeControlAfterBindingChanged(
        changeObject: FormPropertyChangeObject, propertyData: any, parameters: any, viewModelId: string) {

        // 清除绑定：触发界面更新
        if (!changeObject.propertyValue) {
            changeObject['controlEditorChanged'] = true;
            return;
        }

        // 若变更字段类型：清除原控件DOM结构；若当前没有配置控件，则新建控件
        if ((parameters && parameters.fieldTypeChanged) || !propertyData.editor.type) {
            const selectedField = parameters.selectedData;
            const bindingType = changeObject.propertyValue.type;
            propertyData.editor = this.createControl(bindingType, selectedField);

            changeObject['controlEditorChanged'] = true;
        } else {
            // 没有变更字段类型：不需要清除原控件结构，只需要同步更新path属性和帮助相关属性
            this.updateControlDomAfterChangingBinding(changeObject, propertyData.editor, parameters, viewModelId);
        }


    }

    private createControl(bindingType: string, selectedField: any, editorType?: string, oldControl?: any) {
        let editor;
        if (!bindingType) {
            return;
        }
        const hasStateMachine = this.domService.module.stateMachines && this.domService.module.stateMachines.length > 0;

        if (bindingType === FormBindingType.Form) {
            editor = this.controlCreatorSerivice.createTableTdControlBySchemaFeild(selectedField, editorType);
        } else {
            editor = this.controlCreatorSerivice.createTableTdControlByVariable(selectedField, editorType);
        }
        if (!editor.readonly && hasStateMachine) {
            editor.readonly = '!viewModel.stateMachine[\'editable\']';
        }

        if (oldControl) {
            Object.assign(editor, {
                id: oldControl.id,
                isRTControl: !!oldControl.isRTControl,
                appearance: oldControl.appearance,
                size: oldControl.size,
                titleSourceType: oldControl.titleSourceType,
                title: oldControl.title,
                titleDataSource: oldControl.titleDataSource,
                titleWidth: oldControl.titleWidth,
                enableTitleTips: oldControl.enableTitleTips,
                titleTipsTemplate: oldControl.titleTipsTemplate,
                isTextArea: editor.isTextArea && oldControl.isTextArea,
                placeHolder: oldControl.placeHolder,
                holdPlace: oldControl.holdPlace,
                readonly: oldControl.readonly,
                require: oldControl.require,
                visible: oldControl.visible
            });
        }
        return editor;
    }
    private clearControlAfterBindingCleared(oldValue: any, viewModelId: string, propertyData: any) {
        // 清除绑定
        if (oldValue && oldValue.field) {
            const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
            if (!dgViewModel) { return; }

            dgViewModel.removeField([oldValue.field]);

            // 若绑定字段配置了表达式，需要删除表达式
            if (this.domService.expressions && this.domService.expressions.length) {
                const expFieldIndex = this.domService.expressions.findIndex(e => e.fieldId === oldValue.field);
                if (expFieldIndex > -1) {
                    this.domService.expressions.splice(expFieldIndex, 1);
                }

            }
        }

        propertyData.editor = { binding: null, type: null };
    }

    /**
     * 修改绑定后要同步变更控件path属性，若是帮助控件还要变更数据源属性并同步viewModel
     */
    private updateControlDomAfterChangingBinding(
        changeObject: FormPropertyChangeObject, propertyData: any, parameters: any, viewModelId: string) {
        if (!parameters || !parameters.selectedData) {
            return;
        }
        const selectedData = parameters.selectedData;
        // 变更path属性
        propertyData.path = selectedData.bindingPath;
        changeObject.relateChangeProps = [
            {
                propertyID: 'path',
                propertyValue: propertyData.path
            }
        ];

        // 帮助控件变更dataSource.uri属性
        if (propertyData.type === DgControl.LookupEdit.type && propertyData.dataSource && propertyData.dataSource.uri) {
            const uri = propertyData.dataSource.uri;
            const index = uri.indexOf('.');
            if (index < 0) {
                return;
            }

            if (propertyData.binding.type === FormBindingType.Form) {
                const newUri = uri.slice(0, index) + '.' + selectedData.bindingField;
                propertyData.dataSource.uri = newUri;

                // 同步viewModel Field
                const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
                dgViewModel.changeField(propertyData.binding.field, { editor: { dataSource: propertyData.dataSource } });
            } else {
                const newUri = uri.slice(0, index) + '.' + selectedData.code;
                propertyData.dataSource.uri = newUri;
            }

            changeObject.relateChangeProps.push(
                {
                    propertyID: 'dataSource',
                    propertyValue: propertyData.dataSource
                }
            );

        }
    }
}
